Skip to content

fix: add default User-Agent header and optional override#352

Merged
gjtorikian merged 2 commits intomainfrom
feat/user-agent-identifier
Apr 13, 2026
Merged

fix: add default User-Agent header and optional override#352
gjtorikian merged 2 commits intomainfrom
feat/user-agent-identifier

Conversation

@gjtorikian
Copy link
Copy Markdown
Contributor

@gjtorikian gjtorikian commented Apr 13, 2026

Summary

v5 accidentally dropped the outbound User-Agent header identifying the SDK.

This is now restored, resulting in "WorkOS PHP/<Version::SDK_VERSION>" sourced from lib/Version.php. Previously no User-Agent was sent at all, so server-side telemetry couldn't distinguish SDK traffic from other PHP clients.

Every outbound request now sends a User-Agent identifying the SDK
(e.g. "WorkOS PHP/5.0.0"), sourced from Version::SDK_IDENTIFIER /
Version::SDK_VERSION. Wrappers like workos-php-laravel can supply their
own identifier via a new optional userAgent parameter on the WorkOS
constructor, and individual requests can still override via
RequestOptions::extraHeaders.

Precedence: per-request extraHeaders > per-client constructor arg >
default from Version.

Note: lib/WorkOS.php is oagen-generated; the oagen template needs the
same constructor param + forwarding change so the next regeneration
doesn't clobber this.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gjtorikian gjtorikian requested review from a team as code owners April 13, 2026 18:03
@gjtorikian gjtorikian requested a review from nicknisi April 13, 2026 18:03
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 13, 2026

Greptile Summary

Adds a default User-Agent header (WorkOS PHP/<version>) to every outbound request and an optional ?string $userAgent constructor parameter on WorkOS/HttpClient so framework wrappers like workos-php-laravel can supply their own identifier. The header is always applied last in buildRequestOptions, intentionally preventing per-request extraHeaders from overriding it — which is consistent with the code comment and the new test, but contradicts the "Header precedence" table in the PR description.

Confidence Score: 4/5

Safe to merge after addressing the previously-flagged empty-string userAgent passthrough — the new code is otherwise clean and well-tested.

All new findings in this pass are P2. However, the P1 empty-string edge case raised in a prior review thread (passing userAgent: '' sends a blank User-Agent instead of falling back to the SDK default, because ?? only coalesces null) remains unaddressed in this revision, keeping the score at 4/5.

lib/HttpClient.php — the $this->userAgent ?? coalescing at line 195 should also guard against empty string to match the intent of the default fallback.

Important Files Changed

Filename Overview
lib/HttpClient.php Adds ?string $userAgent constructor param and sets User-Agent header last in buildRequestOptions, intentionally preventing per-request extraHeaders from overriding it; empty-string passthrough issue flagged in a previous thread remains open.
lib/WorkOS.php Clean two-line change: adds ?string $userAgent = null parameter and forwards it to HttpClient constructor; no logic changes.
tests/Service/RuntimeBehaviorTest.php Adds three User-Agent tests; the third test name and behavior contradict the PR description's stated header-precedence table (per-request > per-client > default).
tests/TestHelper.php Adds ?string $userAgent = null to createMockClient and forwards it to the WorkOS constructor; minimal, clean change.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant WorkOS
    participant HttpClient
    participant Guzzle

    Caller->>WorkOS: new WorkOS(userAgent: "WorkOS PHP Laravel/5.1.0")
    WorkOS->>HttpClient: new HttpClient(..., userAgent: "WorkOS PHP Laravel/5.1.0")

    Caller->>WorkOS: getOrganization('org_123', RequestOptions?)
    WorkOS->>HttpClient: request(...)
    HttpClient->>HttpClient: buildRequestOptions()
    Note over HttpClient: 1. Set Content-Type, Authorization
    Note over HttpClient: 2. Merge extraHeaders (may include User-Agent)
    Note over HttpClient: 3. Overwrite User-Agent last<br/>→ $userAgent ?? "WorkOS PHP/5.0.0"
    HttpClient->>Guzzle: request(headers: {User-Agent: "WorkOS PHP Laravel/5.1.0", ...})
    Guzzle-->>HttpClient: Response
    HttpClient-->>WorkOS: decoded array
    WorkOS-->>Caller: result
Loading

Reviews (2): Last reviewed commit: "fix: preserve UA string versioning" | Re-trigger Greptile

@gjtorikian gjtorikian changed the title feat: add default User-Agent header and optional override fix: add default User-Agent header and optional override Apr 13, 2026
@gjtorikian gjtorikian merged commit 8e202db into main Apr 13, 2026
10 checks passed
@gjtorikian gjtorikian deleted the feat/user-agent-identifier branch April 13, 2026 18:31
gjtorikian added a commit to workos/workos-php-laravel that referenced this pull request Apr 13, 2026
Pass the Laravel package's Version::SDK_IDENTIFIER and SDK_VERSION as
the userAgent constructor argument so every request originating from
this package is sent with `User-Agent: WorkOS PHP Laravel/<version>`.
This restores the SDK distinguishability that was lost when v5 of
workos/workos-php removed the static `WorkOS::setIdentifier` helper.

Requires workos/workos-php >= 5.0.1, which adds the userAgent
constructor parameter (workos/workos-php#352).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant